package deviceConfig

import (
	"context"
	"devops-super/api"
	v1 "devops-super/api/configs/v1"
	"devops-super/internal/consts"
	"devops-super/internal/consts/cacheConsts"
	"devops-super/internal/dao"
	"devops-super/internal/model/entity"
	"devops-super/internal/model/mymodel"
	"devops-super/internal/service"
	"errors"
	"github.com/gogf/gf/v2/util/gconv"
)

// sDeviceConfig 设备配置逻辑实现
type sDeviceConfig struct{}

func init() {
	service.RegisterDeviceConfig(New())
}

// New 创建设备配置逻辑实例
func New() *sDeviceConfig {
	return &sDeviceConfig{}
}

// Add 新增设备配置
func (*sDeviceConfig) Add(ctx context.Context, in *entity.AppDeviceConfig) (err error) {
	// 检查配置键是否已存在
	count, _ := dao.AppDeviceConfig.Ctx(ctx).
		Where(dao.AppDeviceConfig.Columns().DeviceNo, in.DeviceNo).
		Where(dao.AppDeviceConfig.Columns().ConfigKey, in.ConfigKey).
		Count()
	if count > 0 {
		return errors.New("该设备配置组下的配置键已存在")
	}
	// 插入设备配置记录
	_, err = dao.AppDeviceConfig.Ctx(ctx).Insert(in)
	return
}

// Upt 更新设备配置
func (*sDeviceConfig) Upt(ctx context.Context, in *entity.AppDeviceConfig) (err error) {
	// 检查配置是否存在
	count, _ := dao.AppDeviceConfig.Ctx(ctx).WherePri(in.Id).Count()
	if count == 0 {
		return errors.New("设备配置不存在")
	}
	// 检查配置键是否已被其他记录使用
	count, _ = dao.AppDeviceConfig.Ctx(ctx).
		Where(dao.AppDeviceConfig.Columns().DeviceNo, in.DeviceNo).
		Where(dao.AppDeviceConfig.Columns().ConfigKey, in.ConfigKey).
		Where(dao.AppDeviceConfig.Columns().Id+" != ", in.Id).
		Count()
	if count > 0 {
		return errors.New("该设备配置组下的配置键已存在")
	}
	// 更新设备配置记录
	_, err = dao.AppDeviceConfig.Ctx(ctx).WherePri(in.Id).OmitNilData().Data(in).Update()

	// 删除缓存
	cacheKey := cacheConsts.GetDeviceConfigKey(in.DeviceNo, in.ConfigKey)
	_, _ = service.GetCacheInstance().Remove(ctx, cacheKey)

	return
}

// GetPageLst 分页获取设备配置列表
func (*sDeviceConfig) GetPageLst(ctx context.Context, in *api.PageLstReq) (out *api.PageLstRes[*entity.AppDeviceConfig], err error) {
	out = &api.PageLstRes[*entity.AppDeviceConfig]{}
	m := dao.AppDeviceConfig.Ctx(ctx).Safe(true)

	// 设备编号筛选
	if deviceNo := in.Wheres.Get("deviceNo"); !deviceNo.IsNil() {
		m = m.Where(dao.AppDeviceConfig.Columns().DeviceNo, deviceNo.String())
	}
	// 配置键筛选
	if configKey := in.Wheres.Get("configKey"); !configKey.IsNil() {
		m = m.Where(dao.AppDeviceConfig.Columns().ConfigKey+" like ? ", "%"+configKey.String()+"%")
	}
	// 分页查询
	err = m.Offset(in.Offset()).Limit(in.Limit()).ScanAndCount(&out.List, &out.Total, false)
	return
}

// Del 删除设备配置
func (*sDeviceConfig) Del(ctx context.Context, id int) (err error) {
	// 先查询配置信息
	config := &entity.AppDeviceConfig{}
	err = dao.AppDeviceConfig.Ctx(ctx).WherePri(id).Scan(config)
	if err != nil || config.Id == 0 {
		return errors.New("配置不存在")
	}
	// 删除缓存
	cacheKey := cacheConsts.GetDeviceConfigKey(config.DeviceNo, config.ConfigKey)
	_, _ = service.GetCacheInstance().Remove(ctx, cacheKey)
	// 删除设备配置
	_, err = dao.AppDeviceConfig.Ctx(ctx).WherePri(id).Delete()
	return
}

// GetOne 获取单条设备配置
func (*sDeviceConfig) GetOne(ctx context.Context, id int) (out *entity.AppDeviceConfig, err error) {
	out = new(entity.AppDeviceConfig)
	err = dao.AppDeviceConfig.Ctx(ctx).WherePri(id).Scan(&out)
	return
}

// GetConfig 获取设备配置
func (*sDeviceConfig) GetConfig(ctx context.Context, in *v1.GetDeviceConfigReq) (out *v1.GetDeviceConfigRes, err error) {
	out = &v1.GetDeviceConfigRes{}
	row := new(entity.AppDeviceConfig)
	// 先取缓存
	cacheKey := cacheConsts.GetDeviceConfigKey(in.DeviceNo, in.ConfigKey)

	needGetFromDb := false
	// 先从缓存读取
	if v, err := service.GetCacheInstance().Get(ctx, cacheKey); err == nil && !v.IsEmpty() {
		err = v.Struct(row)
		if err != nil {
			needGetFromDb = true
			// 说明缓存结构体不对 则需要清理
			_, _ = service.GetCacheInstance().Remove(ctx, cacheKey)
		}
	} else {
		needGetFromDb = true
	}
	if needGetFromDb {
		// 查询配置项
		_ = dao.AppDeviceConfig.Ctx(ctx).
			Where(dao.AppDeviceConfig.Columns().DeviceNo, in.DeviceNo).
			Where(dao.AppDeviceConfig.Columns().ConfigKey, in.ConfigKey).
			Scan(&row)
		if row.Id > 0 {
			err = service.GetCacheInstance().Set(ctx, cacheKey, row, 0)
			if err != nil {
				return nil, err
			}
		}
	}
	if row.Id == 0 {
		return
	}
	out.Id = row.Id
	out.ConfigValue = row.ConfigValue
	out.UpdatedAt = gconv.String(row.UpdatedAt.Unix())
	return
}

// SetConfig 保存设备配置
func (s *sDeviceConfig) SetConfig(ctx context.Context, in *v1.SetDeviceConfigReq) (res *v1.SetDeviceConfigRes, err error) {
	res = &v1.SetDeviceConfigRes{}
	deviceNo := in.DeviceNo
	copyDevices := in.CopyDevices
	configValue := in.ConfigValue
	switch in.ConfigKey {
	case consts.DeviceConfTypeParamConfig:
		var config *mymodel.AeParamConfItem
		err = gconv.Struct(configValue, &config)
		if err != nil {
			return res, err
		}
		err = s.SetIotAeParamConfig(ctx, deviceNo, copyDevices, config)
	case consts.DeviceConfTypeFirConfig:
		var config *mymodel.AeFirConfItem
		err = gconv.Struct(configValue, &config)
		if err != nil {
			return res, err
		}
		err = s.SetIotAeFirConfig(ctx, deviceNo, copyDevices, config)
	case consts.DeviceConfTypeLevelConfig2:
		var config *mymodel.AeLevelConfItem2
		err = gconv.Struct(configValue, &config)
		if err != nil {
			return res, err
		}
		err = s.SetIotAeDeviceLevelConfig2(ctx, deviceNo, copyDevices, config)
	case consts.DeviceConfTypeAeFftConfig:
		var config *mymodel.AeFFTConfItem
		err = gconv.Struct(configValue, &config)
		if err != nil {
			return res, err
		}
		err = s.SetIotAeDeviceAeFFTConfig(ctx, deviceNo, copyDevices, config)
	case consts.DeviceConfTypeTimingConfig:
		var config *mymodel.AeTimingConfItem
		err = gconv.Struct(configValue, &config)
		if err != nil {
			return res, err
		}
		err = s.SetIotAeDeviceTimingConfig(ctx, deviceNo, copyDevices, config)
	case consts.DeviceConfTypeFrpConfig:
		var config *mymodel.AeFrpItem
		err = gconv.Struct(configValue, &config)
		if err != nil {
			return res, err
		}
		err = s.SetIotAeDeviceFrpConfig(ctx, deviceNo, copyDevices, config)
	case consts.DeviceConfTypeViMeasureConfig:
		var config *mymodel.ViMeasureConfItem
		err = gconv.Struct(configValue, &config)
		if err != nil {
			return res, err
		}
		err = s.SetViDeviceMeasureConfig(ctx, deviceNo, copyDevices, config)
	default:
		err = errors.New("config type not support")
	}

	return
}
